/*
 * @Author: your name
 * @Date: 2021-01-18 22:06:17
 * @LastEditTime: 2021-01-27 23:34:41
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \6_bldc\bsp\stm32g474\stm32_adc.c
 */
#if 1
#include "initfunc.h"
#include "stm32_adc.h"
#include "stm32_gpio.h"
/*!< Delay required between ADC end of calibration and ADC enable */
#define ADC_DELAY_CALIB_ENABLE_ADC_CYCLES (4UL)
#define DMA_CHANNEL_1 0x00000000U

#define ADC_CHANNEL_COUN 6                                       //通道数量
#define ADC_ADD_COUN 10                                          //每通道累加个数
#define ADC_DATA_COUNTER 5                                       //每通道平均个数
#define ADC1_DR_Address ((u32)((ADC_TypeDef *)ADC1_BASE + 0x40)) //采样结果地址ADC1
#define ADC_DELAY_CALIB_ENABLE_CPU_CYCLES (ADC_DELAY_CALIB_ENABLE_ADC_CYCLES * 32)

struct
{
  vu32 DataTemp[ADC_CHANNEL_COUN];              //采样累积寄存器
  vu16 DataCouter[ADC_CHANNEL_COUN];            //平均值计数
  vu16 Buffer[ADC_CHANNEL_COUN * ADC_ADD_COUN]; //采样过程缓存
  vu16 OutputData[ADC_CHANNEL_COUN];            //采样结果输出寄存器，一个通道放一位
} AdcData;

/**
 * @description: 开启ADC的DMA时钟和中断
 * @param {*}
 * @return {*}
 */
void DMA1_AdcConfig(DMA_TypeDef *DMAx, uint32_t Channel)
{
  __IO uint32_t tmpreg;
  //开启时钟
  SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMAMUX1EN);
  /* Delay after an RCC peripheral clock enabling */
  tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMAMUX1EN);
  (void)tmpreg;
  SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA1EN);
  /* Delay after an RCC peripheral clock enabling */
  tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA1EN);
  (void)tmpreg;
  //开启中断
  NVIC_SetPriority(DMA1_Channel1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 3, 1));
  NVIC_EnableIRQ(DMA1_Channel1_IRQn);

  //复位DMA1

  //配置DMA1
}

void ADC1_Config(void)
{
  //__IO uint32_t wait_loop_index = 0U;
  __IO uint32_t tmpreg;
  //打开引脚时钟
  GPIO_EnablePort(GPIOA);
  GPIO_EnablePort(GPIOC);
  //打开外设时钟
  SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_ADC12EN);
  /* Delay after an RCC peripheral clock enabling */
  tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_ADC12EN);
  (void)tmpreg;

  //引脚配置
  GPIO_Config(GPIOA, 0, GPIO_MODE_ANALOG, 0, 0, GPIO_PULL_NO);
  GPIO_Config(GPIOA, 1, GPIO_MODE_ANALOG, 0, 0, GPIO_PULL_NO);
  GPIO_Config(GPIOC, 0, GPIO_MODE_ANALOG, 0, 0, GPIO_PULL_NO);
  GPIO_Config(GPIOC, 2, GPIO_MODE_ANALOG, 0, 0, GPIO_PULL_NO);

  DMA1_AdcConfig(DMA1, DMA_CHANNEL_1);
}

/**
 * @description: 
 * @param {*}
 * @return {*}
 */
void ADC_GetValue(void)
{
  u32 temp = 0;
  u8 i = 0;
  u8 ChannelTemp = 0;
  for (ChannelTemp = 0; ChannelTemp < ADC_CHANNEL_COUN; ChannelTemp++)
  {
    temp = 0;
    for (i = 0; i < ADC_ADD_COUN; i++)
    {
      temp += AdcData.Buffer[i * ADC_CHANNEL_COUN + ChannelTemp];
    }
    temp = temp / ADC_ADD_COUN;
    if (temp > 60000)
    {
      temp = 60000;
    }
    AdcData.DataTemp[ChannelTemp] += temp;
    AdcData.DataCouter[ChannelTemp]++;
    if (AdcData.DataCouter[ChannelTemp] >= ADC_DATA_COUNTER)
    {
      AdcData.OutputData[ChannelTemp] = (u16)(AdcData.DataTemp[ChannelTemp] / ADC_DATA_COUNTER);
      AdcData.DataTemp[ChannelTemp] = 0;
      AdcData.DataCouter[ChannelTemp] = 0;
    }
  }
}

__STATIC_INLINE void ADC_REG_StartConversion(ADC_TypeDef *ADCx)
{
  /* Note: Write register with some additional bits forced to state reset     */
  /*       instead of modifying only the selected bit for this function,      */
  /*       to not interfere with bits with HW property "rs".                  */
  MODIFY_REG(ADCx->CR,
             (ADC_CR_ADCAL | ADC_CR_JADSTP | ADC_CR_ADSTP | ADC_CR_JADSTART | ADC_CR_ADSTART | ADC_CR_ADDIS | ADC_CR_ADEN),
             ADC_CR_ADSTART);
}

__STATIC_INLINE uint32_t DMA_IsActiveFlag_TC1(DMA_TypeDef *DMAx)
{
  return ((READ_BIT(DMAx->ISR, DMA_ISR_TCIF1) == (DMA_ISR_TCIF1)) ? 1UL : 0UL);
}
__STATIC_INLINE void DMA_ClearFlag_GI1(DMA_TypeDef *DMAx)
{
  WRITE_REG(DMAx->IFCR, DMA_IFCR_CGIF1);
}

/**
 * @description: 
 * @param {*}
 * @return {*}
 */
void DMA1_Channel1_IRQHandler(void)
{
  if (DMA_IsActiveFlag_TC1(DMA1) == 1)
  {
    ADC_GetValue();
    ADC_REG_StartConversion(ADC1); //必须打开
    DMA_ClearFlag_GI1(DMA1);       //清除全局中断标志位
  }
}

#endif